package com.zzyl.nursing.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.common.utils.UserThreadLocal;
import com.huaweicloud.sdk.iotda.v5.model.ListPropertiesRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceMessageRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowProductRequest;
import com.zzyl.common.core.domain.R;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.BoundFamlyDto;
import com.zzyl.nursing.dto.UserLoginRequestDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.service.IFamilyMemberService;
import com.zzyl.nursing.service.WechatService;
import com.zzyl.nursing.vo.ElderFamilyVo;
import com.zzyl.nursing.vo.FamilyElderByPageVo;
import com.zzyl.nursing.vo.FamilyElderVo;
import com.zzyl.nursing.vo.ByDayVo;
import com.zzyl.nursing.vo.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 老人家属Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-19
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService {
    @Autowired
    private FamilyMemberMapper familyMemberMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private WechatService wechatService;
    @Autowired
    private FamilyMemberElderMapper familyMemberElderMapper;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private RoomMapper roomMapper;
    static List<String> DEFAULT_NICK_NAME = ListUtil.of(
            "生活更美好",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝");

    /**
     * 小程序登录
     *
     * @param dto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto dto) {

        //1.获取openid(调用微信的接口获取) ***
        String openid = wechatService.getOpenid(dto.getCode());

        //2.根据openid查询用户
        LambdaQueryWrapper<FamilyMember> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FamilyMember::getOpenId, openid);
        FamilyMember familyMember = getOne(queryWrapper);

        //3.判断用户是否存在，用户不存在，就构建用户
        if (ObjectUtil.isEmpty(familyMember)) {
            /*familyMember = new FamilyMember();
            familyMember.setOpenId(openid);*/
            familyMember = FamilyMember.builder()
                    .openId(openid)
                    .build();
        }

        //4.获取用户的手机号（调用微信的接口获取）***
        String phone = wechatService.getPhone(dto.getPhoneCode());

        //5. 新增或修改用户
        inserOrUpdateFamilyMember(familyMember, phone);

        //6. 把用户的信息封装到token,返回
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", familyMember.getName());
        claims.put("userId", familyMember.getId());
        String token = tokenService.createToken(claims);

        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(familyMember.getName());

        return loginVo;
    }

    /**
     * 新增或修改用户
     *
     * @param familyMember
     * @param phone
     */
    private void inserOrUpdateFamilyMember(FamilyMember familyMember, String phone) {

        //1. 判断新的手机跟数据库中保存的手机号是否一致
        if (ObjectUtil.notEqual(familyMember.getPhone(), phone)) {
            familyMember.setPhone(phone);
        }

        //2. id是否存在，如存在，就修改
        if (ObjectUtil.isNotEmpty(familyMember.getId())) {
            updateById(familyMember);
            return;
        }

        //3. 不存在，就新增 (拼装用户的昵称：随机字符串+手机号后4位)
        int index = (int) (Math.random() * DEFAULT_NICK_NAME.size());
        String nickName = DEFAULT_NICK_NAME.get(index) + phone.substring(phone.length() - 4);
        familyMember.setName(nickName);
        save(familyMember);

    }

    @Override
    public void boundFamly(BoundFamlyDto dto) {
        //判断绑定信息是否为空
        if (StringUtils.isEmpty(dto.getName()) || StringUtils.isEmpty(dto.getIdCard()) || StringUtils.isEmpty(dto.getRemark())) {
            throw new RuntimeException("绑定内容不能为空");
        }
        //判断身份证号格式是否正确
        if (IdcardUtil.isValidCard(dto.getIdCard())) {
            throw new RuntimeException("身份证号格式有误");
        }
        //查询老人信息
        LambdaQueryWrapper<Elder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Elder::getName, dto.getName()).eq(Elder::getIdCardNo, dto.getIdCard());
        Elder elder = elderMapper.selectOne(queryWrapper);
        //判断老人信息是否存在
        if (ObjectUtil.isEmpty(elder)){
            throw new RuntimeException("老人不存在");
        }
        //通过UserThreadLocal获取用户id
        Long userId = UserThreadLocal.getUserId();
//        //通过用户id查找family_member_id
//        LambdaQueryWrapper<FamilyMember> queryWrapper2 = new LambdaQueryWrapper<>();
//        queryWrapper2.eq(FamilyMember::getCreateBy,userId);
//        FamilyMember familyMember = familyMemberMapper.selectOne(queryWrapper2);

//        //用elder.getId()查询check_in表取表中remark中的亲属信息
//        LambdaQueryWrapper<CheckIn> queryWrapper2 = new LambdaQueryWrapper<>();
//        queryWrapper2.eq(CheckIn::getElderId,elder.getId());
//        CheckIn checkIn = checkInMapper.selectOne(queryWrapper2);
//        String remark = checkIn.getRemark();
//        //将remark转回json
//        List<ElderFamilyVo> elderFamilyVoList = JSONUtil.toList(remark, ElderFamilyVo.class);
//        LambdaQueryWrapper<FamilyMember> queryWrapper4 = new LambdaQueryWrapper<>();
//        queryWrapper4.eq(FamilyMember::getName, elderFamilyVoList.get(0).getName())
//                .eq(FamilyMember::getPhone, elderFamilyVoList.get(0).getPhone());

        // 创建查询条件构造器
        LambdaQueryWrapper<FamilyMemberElder> queryWrapper3 = new LambdaQueryWrapper<>();
        // 设置查询条件：family_member_id和elder_id都匹配
        queryWrapper3.eq(FamilyMemberElder::getFamilyMemberId, userId)
                .eq(FamilyMemberElder::getElderId, elder.getId());
        // 执行查询并获取对象
        FamilyMemberElder relation = familyMemberElderMapper.selectOne(queryWrapper3);
        if (ObjectUtil.isNotEmpty(relation)){
            throw new RuntimeException("已绑定过此家人");
        }
        //保存绑定信息
        FamilyMemberElder familyMemberElder = new FamilyMemberElder();
        familyMemberElder.setElderId(elder.getId());
        familyMemberElder.setFamilyMemberId(userId);
        familyMemberElder.setRemark(dto.getRemark());
        familyMemberElderMapper.insert(familyMemberElder);
    }

    @Override
    public List<FamilyElderVo> familyElderList() {
        //获取用户id
        Long userId = UserThreadLocal.getUserId();
        //查询与用户关联的老人信息
        List<FamilyMemberElder> familyMemberElders = familyMemberElderMapper.selectList(new LambdaQueryWrapper<FamilyMemberElder>().eq(FamilyMemberElder::getFamilyMemberId,userId));
        //取出集合中所以对象中的elder_id
        List<Long> elderIds = familyMemberElders.stream().map(FamilyMemberElder::getElderId).collect(Collectors.toList());
        //查询集合elderIds中id对应的老人信息
        List<Elder> elders = elderMapper.selectList(new LambdaQueryWrapper<Elder>().in(Elder::getId,elderIds));
        //封装FamilyElderVo
        List<FamilyElderVo> familyElderVos = elders.stream().map(elder -> {
            FamilyElderVo familyElderVo = new FamilyElderVo();
            //id赋值为FamilyMemberElder中elderid相同是对应的主键id
            familyElderVo.setId(familyMemberElders.stream().filter(familyMemberElder -> familyMemberElder.getElderId().equals(elder.getId())).findFirst().get().getId());
            familyElderVo.setElderName(elder.getName());
            familyElderVo.setElderId(elder.getId());
            familyElderVo.setFamilyMemberId(userId);
            return familyElderVo;
        }).collect(Collectors.toList());
        return familyElderVos;
    }

    @Override
    public Page<FamilyElderByPageVo> familyElderListByPage(Integer pageNum, Integer pageSize) {
        //获取用户id
        Long userId = UserThreadLocal.getUserId();
        //查询与用户关联的老人信息
        List<FamilyMemberElder> familyMemberElders = familyMemberElderMapper.selectList(new LambdaQueryWrapper<FamilyMemberElder>()
                .eq(FamilyMemberElder::getFamilyMemberId,userId));
        //取出集合中所以对象中的elder_id
        List<Long> elderIds = familyMemberElders.stream().map(FamilyMemberElder::getElderId).collect(Collectors.toList());
        //查询集合elderIds中id对应的老人信息
        List<Elder> elders = elderMapper.selectList(new LambdaQueryWrapper<Elder>()
                .in(Elder::getId,elderIds));
        //提取elders集合中的name
        List<String> names = elders.stream().map(Elder::getName).collect(Collectors.toList());
        //查询device表,根据remark查询对象;
        List<Device> devices = deviceMapper.selectList(new LambdaQueryWrapper<Device>()
                .in(Device::getRemark,names));
        //查询room,bed表,根据bedId查询,获取room表的对象
        List<Long> bedIds = elders.stream().map(Elder::getBedId).collect(Collectors.toList());
        //根据床id集合查询bed表获取对象
        List<Bed> beds = bedMapper.selectList(new LambdaQueryWrapper<Bed>()
                .in(Bed::getId,bedIds));
        //获取beds中所有roomId
        List<Long> roomIds = beds.stream().map(Bed::getRoomId).collect(Collectors.toList());
        //根据roomId集合查room表
        List<Room> rooms = roomMapper.selectList(new LambdaQueryWrapper<Room>()
                .in(Room::getId,roomIds));
        //封装FamilyElderByPageVo
        List<FamilyElderByPageVo> familyElderByPageVos = elders.stream().map(elder -> {
            FamilyElderByPageVo familyElderByPageVo = new FamilyElderByPageVo();
            //id赋值为FamilyMemberElder中elderid相同是对应的主键id
            familyElderByPageVo.setMid(familyMemberElders.stream().filter(familyMemberElder ->
                    familyMemberElder.getElderId().equals(elder.getId())).findFirst().get().getId());
            familyElderByPageVo.setMremark(familyMemberElders.stream().filter(familyMemberElder ->
                    familyMemberElder.getElderId().equals(elder.getId())).findFirst().get().getRemark());
            familyElderByPageVo.setElderId(elder.getId());
            familyElderByPageVo.setName(elder.getName());
            familyElderByPageVo.setImage(elder.getImage());
            familyElderByPageVo.setBed_number(elder.getBedNumber());
            familyElderByPageVo.setTypeName(rooms.stream().filter(room ->
                    room.getId().equals(beds.stream().filter(bed -> bed.getId().equals(elder.getBedId()))
                            .findFirst().get().getRoomId())).findFirst().get().getTypeName());
            //注意非空判断
            devices.stream().filter(device -> device.getRemark().equals(elder.getName()))
                    .findFirst()
                    .ifPresent(device -> familyElderByPageVo.setIotId(device.getIotId()));
            devices.stream().filter(device -> device.getRemark().equals(elder.getName())).findFirst()
                    .ifPresent(device -> familyElderByPageVo.setDeviceName(device.getDeviceName()));
            devices.stream().filter(device -> device.getRemark().equals(elder.getName())).findFirst()
                    .ifPresent(device -> familyElderByPageVo.setProductKey(device.getProductKey()));
            return familyElderByPageVo;
        }).collect(Collectors.toList());
        //将familyElderByPageVos封装为Page
        Page<FamilyElderByPageVo> page = new Page<>(pageNum,pageSize);
        page.setRecords(familyElderByPageVos);
        page.setTotal(familyElderByPageVos.size());
        return page;
    }




    /**
     *  按天统计查询指标数据
     * @param functionId
     * @param startTime
     * @param endTime
     * @param iotId
     * @return
     */
    @Override
    public List<ByDayVo> QueryStatisticsByDay(String functionId, Long startTime, Long endTime, String iotId) {

        // 1. 转换为Instant对象（UTC时间）
        Instant  start= Instant.ofEpochMilli(startTime);

        Instant  end= Instant.ofEpochMilli(endTime);
        // 2. 转换为指定时区的时间（如北京时间：Asia/Shanghai）
        //  DateTimeFormatter定义输出格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                .withZone(ZoneId.of("Asia/Shanghai"));
//
        String startTimeNew= formatter.format(start);
        String endTimeNew = formatter.format(end);
        List<ByDayVo> byDayVos = familyMemberMapper.QueryStatisticsByDay(functionId, startTimeNew, endTimeNew, iotId);

        return byDayVos;
    }

    @Override
    public List<ByDayVo> QueryStatisticsByWeek(String functionId, Long startTime, Long endTime, String iotId) {

//        // 定义时间格式化器
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//
//        // 获取当前时间
//        LocalDateTime now = LocalDateTime.now();
//        String formattedNow = now.format(formatter);
//
//        // 获取7天前的时间
//        LocalDateTime sevenDaysAgo = now.minusDays(7);
//        String formattedSevenDaysAgo = sevenDaysAgo.format(formatter);


        // 1. 转换为Instant对象（UTC时间）
        Instant  start= Instant.ofEpochMilli(startTime);

        Instant  end= Instant.ofEpochMilli(endTime);
        // 2. 转换为指定时区的时间（如北京时间：Asia/Shanghai）
        //  DateTimeFormatter定义输出格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                .withZone(ZoneId.of("Asia/Shanghai"));
//
        String startTimeNew= formatter.format(start);
        String endTimeNew = formatter.format(end);
        List<ByDayVo> dataList = familyMemberMapper.queryLast7DaysData(functionId, startTimeNew, endTimeNew, iotId);


        return dataList;
    }

}
